//
//  AppDelegate.swift
//  Biubiubiu
//
//  Created by DevWhan on 2019/5/2.
//  Copyright © 2019 DevWhan. All rights reserved.
//

import Cocoa
import FileKit
import ObjectMapper
import NotificationCenter
import HotKey
fileprivate let StoreKey = "StoreKey"

class Project: Mappable{
    
    var path: String?
    var date: Double?
    var name: String?
    var size: Int?
    
    init() {
    }
    required init?(map: Map) {
    }
    func mapping(map: Map) {
        path <- map["path"]
        date <- map["date"]
        name <- map["name"]
        size <- map["size"]
    }
    
    public func mainDirectory() -> String{
        return path! + "/" + Config.shared.mainDirectory
    }
}

class TargetFile: Mappable{
    required init?(map: Map) {
    }
    
    func mapping(map: Map) {
        url <- map["url"]
        name <- map["name"]
        query <- map["query"]
        previewPath <- map["previewPath"]
    }
    
    
    var url = ""
    var name = ""
    var query = ""
    var previewPath = ""
    var path: Path {
        return Path(url)
    }
    
    var select = false
    init(url: String) {
        self.url = url
    }
    
    public func getFileName(replace: String?) -> String{
        if let c = replace{
            return path.fileName.replacingOccurrences(of: c, with: "")
        }else{
            return path.fileName
        }
    }
    
    public func getShowName(replace: String) -> String{
        let fileName = self.getFileName(replace: replace)
        if self.name.count > 0 {
            if self.query.count > 0 {
                return "\(self.name): \(fileName)?\(self.query)"
            }else{
                return "\(self.name): \(fileName)?"
            }
        }else{
            if self.query.count > 0 {
                return "\(fileName)?\(self.query)"
            }else{
                return "\(fileName)"
            }
        }
    }
    
    public func getFileQueryString() -> String{
        if self.query.count > 0 {
            return self.path.fileName + "?" + self.query
        }else{
            return self.path.fileName
        }
    }
}

extension TargetFile: CustomDebugStringConvertible {
    var debugDescription: String{
        return path.fileName + " " + name + " " + query
    }
}

class Config: NSObject {
    static let shared = Config()
    let mainDirectory   = "dist"
    let fileNameOfPreview = "preview.config.js"
    let preview_main = "pages"
    let preview_name = "name"
    let preview_path = "path"
    let preview_query = "query"
}

enum TargetSize {
    case normal
    case small
    
    func getSize() -> CGSize {
        switch self {
        case .normal:
            return CGSize(width: 250, height: 500)
        case .small:
            return CGSize(width: 120, height: 250)
        }
    }
}

let Notification_ShowBiuView = "Notification_ShowBiuView"
let Notification_ChangeSkip = Notification.Name(rawValue: "Notification_ChangeSkip")
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var statusItem: NSStatusItem!
    var popover = NSPopover()
    var isSkip = false
    let hotKey = HotKey(key: .b, modifiers: [.command, .option])
    let searcgHotKey = HotKey(key: .s, modifiers: [.command, .option])
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        setupStatusItem()
        NotificationCenter.default.addObserver(self, selector: #selector(statusItemClick), name: NSNotification.Name(rawValue: Notification_ShowBiuView), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(changeSkipMode), name: Notification_ChangeSkip, object: nil)
        
//        popover.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark)
//        popover.contentViewController = ChooseController()
//        popover.contentSize = NSSize(width: 250, height: 500)
//        popover.behavior = .transient
    }
    
    public func setupStatusItem(){
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        statusItem.button?.image = NSImage(named: NSImage.Name("biubiubiu"))
        statusItem.button?.toolTip = "Biubiubiu"
        statusItem.button?.action = #selector(statusItemClick)
        
        let menu = NSMenu(title: "Choose")
        menu.addItem(NSMenuItem(title: "Open Project", action: #selector(open), keyEquivalent: ""))
        menu.addItem(NSMenuItem.separator())
        
        //history
        //        UserDefaults.standard.set(nil, forKey: StoreKey)
        let storeProject = getStoreProject()
        if !storeProject.isEmpty {
            let menuItems = storeProject.map{ NSMenuItem(title: $0.name!, action: #selector(historyClick(item:)), keyEquivalent: $0.path!) }
            menuItems.forEach { (item) in
                menu.addItem(item)
            }
            menu.addItem(NSMenuItem.separator())
        }
        
        //        menu.addItem(NSMenuItem(title: "Preference", action: #selector(quit), keyEquivalent: ""))
        menu.addItem(NSMenuItem(title: "Quit", action: #selector(quit), keyEquivalent: ""))
        statusItem.menu = menu
    
        hotKey.keyDownHandler = {
            if(self.popover.contentViewController != nil){
                self.statusItemClick()
            }
        }
        searcgHotKey.keyDownHandler = {
            if let biu = self.popover.contentViewController as? BiuViewController {
                biu.searchView.becomeFirstResponder()
            }
        }
    }
    
    @objc public func open(){
        openPanel()
    }
    
    @objc public func quit(){
        exit(0)
    }
    
    @objc public func historyClick(item: NSMenuItem){
        let storeProject = getStoreProject()
        if let project = storeProject.first(where: { $0.path! == item.keyEquivalent}) {
            toOperationView(project: project)
        }else{
            //delete
        }
    }
    
    fileprivate func openPanel(){
        let openPanel = NSOpenPanel()
        //            openPanel.delegate = self
        openPanel.canChooseFiles = false
        openPanel.canChooseDirectories = true
        openPanel.allowsMultipleSelection = false
        openPanel.message = "选择项目目录"
        
        openPanel.begin { (result) in
            if result == NSApplication.ModalResponse.OK {
                if let path = openPanel.urls.first?.path {
                    self.chooseDirectories(path: path)
                }
            }
        }
        NSApp.activate(ignoringOtherApps: true)
        openPanel.makeKeyAndOrderFront(self)
    }
    
    fileprivate func chooseDirectories(path: String){
        let filePath = Path(path)
        let isWeexD = filePath.children().contains { item -> Bool in
            return item.rawValue.contains("dist")
        }
        if isWeexD {
            
            let project = Project()
            project.path = filePath.rawValue
            project.date = Date().timeIntervalSince1970
            project.name = filePath.fileName
            
            toOperationView(project: project)
        }else{
            let alert = NSAlert()
            alert.messageText = "请选择正确的weex项目文件夹, 文件夹中应包含dist目录"
            alert.alertStyle = .informational
            alert.addButton(withTitle: "取消")
            alert.addButton(withTitle: "重新选择")
            
            alert.beginSheetModal(for: statusItem.button!.window!) { (res) in
                if res != NSApplication.ModalResponse.cancel {
                    self.openPanel()
                }
            }
        }
    }
    
    fileprivate func toOperationView(project: Project){
        
        //save
        saveThisProject(project: project)
        var size: TargetSize = .normal
        if let lastSize = project.size {
            size = lastSize == 0 ? .normal : .small
        }
        toOperationView(project: project, size: size, ip: nil, filterContainString: nil)
    }
    
    public func toOperationView(project: Project,size: TargetSize, ip: String?, filterContainString: String?){
        let biuVc = BiuViewController(project: project,size: size ,ip: nil, filterContainString: filterContainString)
        popover.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark)
        popover.contentViewController = biuVc
        popover.contentSize = size.getSize()
        if size == .normal {
            popover.behavior = .transient
        }else{
            popover.behavior = .applicationDefined
        }
        statusItem.menu = nil
        statusItemClick()
    }
    
    
    @objc public func statusItemClick(){
        popover.show(relativeTo: statusItem.button!.bounds, of: statusItem.button!, preferredEdge: .maxY)
    }
    
    public func saveThisProject(project: Project){
        var storeProject = getStoreProject()
        if let index = storeProject.firstIndex(where: { $0.path! == project.path! }) {
            storeProject.remove(at: index)
            storeProject.append(project)
        }else{
            storeProject.append(project)
        }
        
        if let storeString = storeProject.toJSONString() {
            UserDefaults.standard.set(storeString, forKey: StoreKey)
        }
    }
    
    public func getStoreProject() -> [Project] {
        if let storeArrayString = UserDefaults.standard.object(forKey: StoreKey) as? String{
            if let result = Mapper<Project>().mapArray(JSONString: storeArrayString) {
                return result
            }
        }
        return [Project]()
    }
    
    public func addGloalMonitorMouseDown(){
        NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDown) {[weak self] (event) in
            if let strongSelf = self {
                if strongSelf.popover.isShown, !strongSelf.isSkip {
                    strongSelf.popover.close()
                }
            }
        }
    }
    
    @objc public func changeSkipMode(){
        self.isSkip = !self.isSkip
        if self.isSkip {
            popover.contentSize = NSSize(width: 100, height: 300)
        }else{
            popover.contentSize = NSSize(width: 250, height: 500)
        }
    }
    
    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    
    

}

